/*
************************************************************************************************************************************
*                                          GPRS DATA TRANSMISSION SERVICE 
*                                                  BASE ON PROTOCOL
*                                <<DATA TRANSMISSION PROTOCO V1.0 update20120801>>
*                                       (c) Copyright 2012 all right reserved
************************************************************************************************************************************
*
* Filename      : CommInterface.c
* Version       : V0.01
* Programmer    : Z
* Date          : 2013-05-21
************************************************************************************************************************************
*/

/*
************************************************************************************************************************************
*                                             INCLUDE FILES
************************************************************************************************************************************
*/

#include <string.h>
#include "includes.h"

#include "gd32f307c_eval.h"
#include "CommInterface.h"
#include "globle.h"
#include "netconf.h"
#include "udp_echo.h"


#ifdef USE_UDP_TCP_NET
#include "app_lwip.h"
#endif


#ifdef USE_RS232_RS485
#include "Com.h"
#endif


#ifdef USE_USB_OTG_FS   
#include "app_usbh.h"
#endif
/*
************************************************************************************************************************************
*                                     GPRSchip and MCU  COMx port hardware configure
************************************************************************************************************************************
*/



/*
************************************************************************************************************************************
*                                             globle DEFINES&DATA TYPES
************************************************************************************************************************************
*/

COMMCHL  gCommWay;
#if (defined USE_UDP_TCP_NET) || (defined USE_RS232_RS485)
T08U    rxbuffer [MAX_MSG_SIZE];
#endif

#if (defined USE_UDP_TCP_NET) 
T08U    udpbuffer[MAX_MSG_SIZE];
#endif
T08U     *prxbuf;
T32U    rxsize;
OS_EVENT * CommRxMsgSem;
OS_EVENT * USBHRxMsgSem;

const T08U FrameHeader[4] = {0x55,0xAA,0x00,0x00};

/*
************************************************************************************************************************************
*                                            LOCAL VARIABLES
************************************************************************************************************************************
*/




#ifdef USE_RS232_RS485

#define COM232                                            COM1	  /* RS232   */
#define COM485                                            COM2    /* RS485   */

#define  SERIAL_PORT_TASK_PRIO                            9
#define  SERIAL_PORT_TASK_STK_SIZE                        192

static OS_STK   SerialPortTaskStk[SERIAL_PORT_TASK_STK_SIZE];

static void     SerialPortTask  (void *p_arg);
#endif	/* USE_RS232_RS485 */


#ifdef USE_UDP_TCP_NET

#define  TCP_CLI_TASK_PRIO                                8
#define  TCP_CLI_TASK_STK_SIZE                            448


#define  TCP_SERV_TASK_PRIO                               7
#define  TCP_SERV_TASK_STK_SIZE                           448

static OS_STK   TcpServTaskStk[TCP_SERV_TASK_STK_SIZE];
static OS_STK   TcpCliTaskStk[TCP_CLI_TASK_STK_SIZE];

static void     TcpCliTask  (void *p_arg);
static void     TcpServTask   (void *p_arg);

#endif	/* USE_UDP_TCP_NET */


/*
************************************************************************************************************************************
*                                        LOCAL FUNCTION PROTOTYPES
************************************************************************************************************************************
*/
/*
************************************************************************************************************************************
*Description :GPRS initialization .
*Arguments   :none.
*Returns     :if( > 0) : GPRS initialization ok and the device is online.
*             if( < 0) : GPRS initialization error and the device is offline.
*Callers     :application.
*Notes       :none.
************************************************************************************************************************************
*/

T32S CommInit(COMMCFG *p)
{
#ifdef USE_RS232_RS485
    Baud   b232;
    Format f232;
    switch((*p).Rs232[0]) {
    case 0: b232 = _9600bps;  break;
    case 1: b232 = _115200bps;break;
    case 2: b232 = _57600bps; break;
    case 3: b232 = _19200bps; break;
    case 4: b232 = _28800bps; break;
    case 5: b232 = _38400bps; break;
    default:b232 = _57600bps;
    }
    switch((*p).Rs232[2]) {
    case 0: f232 = _8N1; break;
    case 1: f232 = _8E1; break;
    case 2: f232 = _8O1; break;
    case 3: f232 = _8N2; break;
    case 4: f232 = _7E1; break;
    case 5: f232 = _7O1; break;
    case 6: f232 = _7N2; break;
    default:f232 = _8N1;
    }

    ComInit(COM232,f232,b232);
    ComInit(COM485,f232,b232);
#endif
    
#ifdef USE_UDP_TCP_NET
    enet_system_setup();
    printf("enet sysytem setup OK\r\n");
    lwip_stack_init();
    udp_echo_init();
    //NetTcpUdpInit((*p).NetIP,(*p).NetMASK,(*p).NetGATE,(*p).NetMAC,(T16U)((*p).NetPORT[1]*0x100 + (*p).NetPORT[0]));
#endif
    
#ifdef USE_USB_OTG_FS   
    USBH_APP_Init();
#endif    
/*----------------------------------------------------------------------------------------------------------------------------------*/        
    gCommWay = COMM_CHANNEL_ETH0_TCP_SER;
/*----------------------------------------------------------------------------------------------------------------------------------*/    

    CommRxMsgSem = OSSemCreate(0); 
    USBHRxMsgSem = OSSemCreate(0);

#ifdef USE_UDP_TCP_NET    
//    OSTaskCreateExt((void (*)(void *)) TcpCliTask,  
//                    (void           *) 0,
//                    (OS_STK         *)&TcpCliTaskStk[TCP_CLI_TASK_STK_SIZE - 1],
//                    (INT8U           ) TCP_CLI_TASK_PRIO,
//                    (T16U            ) TCP_CLI_TASK_PRIO,
//                    (OS_STK         *)&TcpCliTaskStk[0],
//                    (T32U            ) TCP_CLI_TASK_STK_SIZE,
//                    (void           *) 0,
//                    (T16U            )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));        
    OSTaskCreateExt((void (*)(void *)) TcpServTask,
                    (void           *) 0,
                    (OS_STK         *)&TcpServTaskStk[TCP_SERV_TASK_STK_SIZE - 1],
                    (INT8U           ) TCP_SERV_TASK_PRIO,
                    (T16U            ) TCP_SERV_TASK_PRIO,
                    (OS_STK         *)&TcpServTaskStk[0],
                    (T32U            ) TCP_SERV_TASK_STK_SIZE,
                    (void           *) 0,
                    (T16U            )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
#endif
#ifdef USE_RS232_RS485    
    OSTaskCreateExt((void (*)(void *)) SerialPortTask,           
                    (void           *) 0,
                    (OS_STK         *)&SerialPortTaskStk[SERIAL_PORT_TASK_STK_SIZE - 1],
                    (INT8U           ) SERIAL_PORT_TASK_PRIO,
                    (T16U            ) SERIAL_PORT_TASK_PRIO,
                    (OS_STK         *)&SerialPortTaskStk[0],
                    (T32U            ) SERIAL_PORT_TASK_STK_SIZE,
                    (void           *) 0,
                    (T16U            )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

#endif
    return 1;      
}

/*
************************************************************************************************************************************
*Description :Send a Message by GPRS.
*Arguments   :msg:the address of message to be sent.
*             size:the size   of message to be sent.
*Returns     :if( >= 0) : a message was sent out with this number bytes.
*             if( <  0) : failed or internal error.
*Callers     :Application
*Notes       :none.
************************************************************************************************************************************
*/

T32S CommTxMessage(T08U* msg,T32U size)
{
    switch(gCommWay){
#ifdef USE_RS232_RS485	
    case COMM_CHANNEL_RS232:
	return ComTxMessage(COM232,msg,size);
    case COMM_CHANNEL_RS485:
	return ComTxMessage(COM485,msg,size);
#endif	
#ifdef USE_UDP_TCP_NET		
    case COMM_CHANNEL_ETH0_TCP_SER:
	return TcpServerTxMessage(msg,size);
    case COMM_CHANNEL_ETH1_UDP_SER:
	return UdpServerTxMessage(msg,size);
    case COMM_CHANNEL_ETH2_TCP_CLI:
	return TcpClientTxMessage(msg,size);
#endif	
    default:return -1;
    }
}
  
/*
************************************************************************************************************************************
*Description :receive a message by gprs.
*Arguments   :msg:the address of a pointer where hold the message received.
*             max_msg_size:the possible  max size of the message received.(while,if max_msg_size > 1460,it's will 
*                          be set to 1460).
*             TimeOutMs:   time out value, use ms  as unit.
*Returns     :if( > 0) : a message received with this number bytes.
*             if( = 0) : timeout happened.
*             if( = -11) :waiting for message in non blocking mode.
*             if( < 0) : internal error.
*Callers     :Application
*Notes       :none.
************************************************************************************************************************************
*/

T32S CommRxMessage(T08U **msg,T32U max_msg_size,T32U TimeOutMs)
{
    INT8U  err;

    if( max_msg_size == 0){
	return -1;
    }
    
    OSSemPend(CommRxMsgSem,(T16U)TimeOutMs,&err);  
    if(err == OS_ERR_NONE) {
//	if(((gInfo.chipstatus & ((T32U)1 << STATUS_BIT_PEND_RESTART_LEDCTRLTASK)) == 0)){ /* pending to recreate LedCtrlTask from USB application */
//	    gInfo.chipstatus |=   1 << STATUS_BIT_PEND_RESTART_LEDCTRLTASK;
//	    LedCtrlTaskDelete();
//	    LedCtrlTaskCreate();
//	    return 0;
//	}
	if(rxsize > max_msg_size ) {
	    return max_msg_size;
	} else if(rxsize == 0){
	    return -2;
	} else {
            *msg = prxbuf; 
	    return rxsize;
	}
    } else if (err == OS_ERR_TIMEOUT) {
	return 0;
    } else {
	return -2;
    }
}




/*
************************************************************************************************************************************
*                   background service  Task of GPRS  communication service layer
************************************************************************************************************************************
*/


/*
************************************************************************************************************************************
*     gprs user config  service  Task,which communicate with a software(usunally installed in windows) by COM232.
************************************************************************************************************************************
*/

#ifdef USE_RS232_RS485
void SerialPortTask  (void *p_arg)
{

    ComxyIf Rs232Rs485;
    T32S    size;

    Rs232Rs485.comx            = COM232;
    Rs232Rs485.comy            = COM485;
    Rs232Rs485.RxBufferx       = rxbuffer;
    Rs232Rs485.RxBuffery       = rxbuffer;
    Rs232Rs485.FrameHeaderx    = FrameHeader;
    Rs232Rs485.FrameHeadery    = FrameHeader;
    Rs232Rs485.HeaderByteNumx  = 4;
    Rs232Rs485.HeaderByteNumy  = 4;
    Rs232Rs485.RxAddrx         = 0x01;
    Rs232Rs485.RxAddry         = gCommCfg.Rs485[1];
    Rs232Rs485.rulex           = ANY_ADDRESS;
    Rs232Rs485.ruley           = SPECIFIC_BROADCAST;
    Rs232Rs485.RxBufferSizex   = MAX_MSG_SIZE;
    Rs232Rs485.RxBufferSizey   = MAX_MSG_SIZE;
    Rs232Rs485.TimeOutMs = 25000;
    while (DEF_TRUE) {
	size =  ComXYRxMessage(&Rs232Rs485);
        if(size >= MIN_MSG_SIZE) {
   	    if(((gInfo.chipstatus & ((T32U)1 << STATUS_BIT_COMM_BUSY)) == 0) && (gCommWay != COMM_CHANNEL_RS232)&& (gCommWay != COMM_CHANNEL_RS485)) {
   		continue;	/* if other comm channel is busy,packet from udp will be discard */
   	    }
#if (DYNAMIC_GB_AREA_MAX > 0)
		if(size > 28                && rxbuffer[7] == OP_WR_DINA_DAT && rxbuffer[20] == '%'){
		    if(DynamicGB2312_data_Process(&rxbuffer[20],size - 24) > 0){
                        /* gCommWay = COMM_CHANNEL_ETH0_TCP_SER;	   */
                        /* TxAckMessage(0x00,OP_WR_DINA_DAT,0x01,gCommCfg.Rs485[1]); */
		    }
		    continue;	/* exit DYNAMIC_GB_AREA_MAX status,wait for new communication session */
		}
#endif	/* DYNAMIC_GB_AREA_MAX */
#if (DYNAMIC___AREA_MAX > 0)
		if(size > 28 && size < 140  && rxbuffer[7] == OP_WR_DINA_DAT && rxbuffer[20] == '#'){
		    if(DynamicASCII_data_Process(&rxbuffer[20],size - 24) > 0){
                        /* gCommWay = COMM_CHANNEL_ETH0_TCP_SER;	   */
                        /* TxAckMessage(0x00,OP_WR_DINA_DAT,0x01,gCommCfg.Rs485[1]); */
		    }
		    continue;	/* exit DYNAMIC__AREA_MAX status,wait for new communication session */
		}
#endif	/* DYNAMIC___AREA_MAX */
#if (TEXT_SPEAKER_AREA_MAX > 0)
		if(size > 28 && size < 512  && rxbuffer[7] == OP_WR_DINA_DAT && rxbuffer[20] == '$'){
		    if(DynamicSpeak_data_Process(&rxbuffer[20],size - 24) > 0){
                        /* gCommWay = COMM_CHANNEL_ETH0_TCP_SER;	   */
                        /* TxAckMessage(0x00,OP_WR_DINA_DAT,0x01,gCommCfg.Rs485[1]); */
		    }
                    continue;
		}
#endif	/* #if (TEXT_SPEAKER_AREA_MAX    > 0) */                		
	    if(Rs232Rs485.Channel == COM232){
		gCommWay = COMM_CHANNEL_RS232;
		prxbuf   = Rs232Rs485.RxBufferx;
		rxsize   = size;
	    } else {
		gCommWay = COMM_CHANNEL_RS485;
		prxbuf   = Rs232Rs485.RxBuffery;
		rxsize   = size;
	    }
    	    OSSemPost(CommRxMsgSem);

    	}
    }

}
#endif
/*
************************************************************************************************************************************
*     gprs user config  service  Task,which communicate with a software(usunally installed in windows) by COM232.
************************************************************************************************************************************
*/

#ifdef USE_UDP_TCP_NET
void UdpServTask  (void *p_arg)
{
    UdpServerProcess();
    OSTaskSuspend(OS_PRIO_SELF);
}
static void TcpServTask  (void *p_arg)
{
   // TcpServerProcess();
    OSTaskSuspend(OS_PRIO_SELF);
}

static void TcpCliTask  (void *p_arg)
{
    TcpClientProcess();
    OSTaskSuspend(OS_PRIO_SELF);
}
#endif

/*
************************************************************************************************************************************
*                                          file end
************************************************************************************************************************************
*/  
